home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / Other Langs / Tickle-4.0 (tcl) / tcl / expecTerm / switch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-17  |  16.0 KB  |  559 lines  |  [TEXT/MPS ]

  1. /* switches.c - terminal switch control
  2. ***************************************************************************** 
  3. expecTerm version 1.0 beta
  4. Mark Weissman
  5. Christopher Matheus
  6. Copyright 1992 by GTE Laboratories Incorporated.
  7.  
  8. Portions of this work are in the public domain.  Permission to use,
  9. copy, modify, and distribute this software and its documentation for
  10. any purpose and without fee is hereby granted, provided that the above
  11. copyright notice appear in all copies and that both the copyright
  12. notice and warranty disclaimer appear in supporting documentation, and
  13. that the names of GTE Laboratories or any of their entities not be
  14. used in advertising or publicity pertaining to distribution of the
  15. software without specific, written prior permission.
  16.  
  17. GTE disclaims all warranties with regard to this software, including
  18. all implied warranties of merchantability and fitness for a particular
  19. purpose, even if GTE Laboratories Incorporated knows about the
  20. purpose.  In no event shall GTE be liable for any special, indirect or
  21. consequential damages or any damages whatsoever resulting from loss of
  22. use, data or profits, whether in an action of contract, negligence or
  23. other tortuous action, arising out of or in connection with the use or
  24. performance of this software.
  25.  
  26. This code is based on and may include parts of Don Libes' expect code:
  27.   expect written by: Don Libes, NIST, 2/6/90
  28.   Design and implementation of expect was paid for by U.S. tax
  29.   dollars.  Therefore it is public domain.  However, the author and NIST
  30.   would appreciate credit if this program or parts of it are used.
  31. ******************************************************************************
  32.  
  33. Written by: Mark Weismann and Chris Matheus  May 1992 
  34.  
  35. */
  36.  
  37. #include <stdio.h>
  38. #include <ctype.h>
  39. #include <tcl.h>
  40. #include "win.h"
  41. #include "global.h"
  42. #include "command.h"
  43. #include "translate.h"
  44.  
  45. extern int fd_max;
  46.  
  47. /*ARGSUSED*/
  48. static int
  49. cmdTermInfo(clientData, interp, argc, argv)
  50. ClientData clientData;
  51. Tcl_Interp *interp;
  52. int argc;
  53. char **argv;
  54. {
  55.   int m = -1, n = -1, writep = 0;
  56.   char nstrings;
  57.   char **strings;
  58.   char buf[BUFSIZ], modearg = 's', mode;
  59.  
  60.   /* get spawn id if any */
  61.   nstrings = argc - 1;
  62.   strings = argv+1;
  63.   if (nstrings < 1) goto usage_error;
  64.   if (streq(*strings,"-i")) {
  65.     --nstrings; ++strings;
  66.     if (nstrings < 1) goto usage_error;
  67.     m = atoi(*strings);
  68.     --nstrings; ++strings;
  69.     if (nstrings < 1) goto usage_error;
  70.   }
  71.   if (streq(*strings,"-type") || streq(*strings,"-local") || streq(*strings,"-transmit")) {
  72.     writep = 1;
  73.     if (streq(*strings,"-type")) modearg = 's';
  74.     else if (streq(*strings,"-local")) modearg = 'L';
  75.     else modearg = 'X';
  76.     --nstrings; ++strings;
  77.     if (nstrings < 1) goto usage_error;
  78.   }
  79.   
  80.   /* get master fd */
  81.   if ((m == -1) && (update_master(&m) == 0)) return(TCL_ERROR);
  82.   if (m == -1) return(TCL_ERROR);
  83.   else if (m <= 2) {
  84.     tcl_error("%s: Invalid Master: %d",argv[0]);
  85.     return(TCL_ERROR);
  86.   }
  87.   if (!SetSessionFromFD(m)) {
  88.     tcl_error("%s: Master: %d Not Associated with emulator.",argv[0],m);
  89.     return(TCL_ERROR);
  90.   }
  91.   for (n=0; n<nstrings; ++n) {
  92.     extern char *LookupCap();
  93.     char *string = LookupCap(Session->term, strings[n]);
  94.     mode = string[strlen(string)+1];
  95.     if (!string) {
  96.       tcl_error("%s: Could Not find Terminfo Capability for: {%s}.",argv[0], strings[n]);
  97.       return(TCL_ERROR);
  98.     }
  99.     if (strchr("sXL", mode)) {
  100.       *buf = '\0';
  101.       if (mode == 'X') strcpy(buf, "-transmit ");
  102.       if (mode == 'L') strcpy(buf, "-local ");
  103.       FixEscapes(buf+strlen(buf), string);
  104.       string = buf;
  105.     }
  106.     Tcl_AppendElement(interp, string, 0);
  107.   }
  108.   for (n=0; writep && n<nstrings; ++n) {
  109.     extern char *LookupCap();
  110.     char *string = LookupCap(Session->term, strings[n]);
  111.     if (!string) {
  112.       tcl_error("%s: Could Not find TERMINFO Capability for: {%s}.",argv[0], strings[n]);
  113.       return(TCL_ERROR);
  114.     }
  115.     /* Look at type code hidden after the string 
  116.        If its 'b' (boolean), or 'n' (numeric) don't send it to terminal
  117.        If its 's' (string) then defer to mode from argument.
  118.        If its 'X' (Transmit string) then terminal said to Transmit this string.
  119.        If its 'L' (Local string) then terminal said to execute this string locally.
  120.        */
  121.     mode = string[strlen(string)+1];
  122.     if (!strchr("sXL", mode)) continue;
  123.     if (mode == 's') mode = modearg;
  124.     if (mode == 'L') {
  125.       char olocal = Session->term->Local;
  126.       Session->term->Local=1;
  127.       Write(Session->fd, string, strlen(string));
  128.       Session->term->Local=olocal;
  129.     }
  130.     else if (mode == 'X') {
  131.       write(Session->fd, string, strlen(string));
  132.       if (Session->term->Local) {
  133.     char cr='\r', nl='\n';
  134.     write(Session->fd, &cr, 1);
  135.     if (Session->term->bool_hpAutoLinefeed==1) write(Session->fd, &nl, 1);
  136.       }
  137.     }
  138.     else 
  139.       Write(Session->fd, string, strlen(string));
  140.   }
  141.   return(TCL_OK);
  142.   
  143.  usage_error:
  144.   tcl_error("usage: %s [-i spawn_id] [-type | -local | -transmit] [terminfo-capability-name]+", argv[0]);
  145.   return(TCL_ERROR);
  146. }
  147.  
  148. /*ARGSUSED*/
  149. static int
  150. cmdSetMaster(clientData, interp, argc, argv)
  151. ClientData clientData;
  152. Tcl_Interp *interp;
  153. int argc;
  154. char **argv;
  155. {
  156.   int m = -1, n = -1, terminalp, i, refreshp=0, was_terminalp;
  157.   char tempbuf[80];
  158.   extern char in_curses;
  159.   extern int loguser;
  160.  
  161.   /* get spawn id if any */
  162.   for (i=1;i<argc;i++) {
  163.     if (streq(argv[i],"-i")) {
  164.       if (argc == ++i) goto usage_error;
  165.       m = atoi(argv[i]);
  166.       break;
  167.     }
  168.   }
  169.   
  170.   /* get master fd */
  171.   if ((m == -1) && (update_master(&m) == 0)) return(TCL_ERROR);
  172.   if (m == -1) return(TCL_ERROR);
  173.   else if (m <= 2) {
  174.     tcl_error("%s: Invalid Master: %d",argv[0]);
  175.     return(TCL_ERROR);
  176.   }
  177.   was_terminalp = SetSessionFromFD(m);
  178.   n=m;
  179.       
  180.   /* parse rest of arguments */
  181.   for (i=1;i<argc;i++) {
  182.     if (streq(argv[i],"-i")) i++;
  183.     else if (streq(argv[i],"-next")) {
  184.       while (TRUE) {
  185.     if (++n > fd_max) n=0;
  186.     if ((n==m) || (!is_user(n) && fs[n].pid && (fs[n].flags & FD_VALID))) break;
  187.       }
  188.     } 
  189.     else if (streq(argv[i],"-prev")) {
  190.       while (TRUE) {
  191.     if (--n < 0) n=fd_max;
  192.     if ((n==m) || (!is_user(n) && fs[n].pid && (fs[n].flags & FD_VALID))) break;
  193.       }
  194.     } else if (streq(argv[i],"-refresh")) {
  195.       refreshp = 1;
  196.     } else goto usage_error;
  197.   }
  198.   
  199.   terminalp = SetSessionFromFD(n);
  200.   SetCurrSession();
  201.   sprintf(interp->result,"%d", n);
  202.  
  203.   if (refreshp) ResetWindow();
  204.   if (!terminalp) {
  205.     if (was_terminalp && loguser) system("clear");
  206.     sprintf(tempbuf,"\r\nResuming Master: %d, pid: %d\r\n", n, fs[n].pid);
  207.     write(1,tempbuf,strlen(tempbuf));
  208.   }
  209.   sprintf(tempbuf,"%d",n);
  210.   Tcl_SetVar(interp,"spawn_id",tempbuf,0);
  211.   return(TCL_OK);
  212.   
  213.  usage_error:
  214.   tcl_error("usage: %s [-i spawn_id | -next | -prev] [-refresh]", argv[0]);
  215.   return(TCL_ERROR);
  216. }
  217.  
  218. /*ARGSUSED*/
  219. static int
  220. cmdStatusLine(clientData, interp, argc, argv)
  221. ClientData clientData;
  222. Tcl_Interp *interp;
  223. int argc;
  224. char **argv;
  225. {
  226.   int m = -1, i, refreshp = 0;
  227.   static char *prev = "-default";
  228.   char *text = NULL;
  229.   WinbarP = 1;
  230.   if ((m == -1) && (update_master(&m) == 0)) return(TCL_ERROR);
  231.   if (m == -1) return(TCL_ERROR);
  232.   SetSessionFromFD(m);
  233.   for(i=1; i < argc; ++i) {
  234.     extern char *GetStatusLine();
  235.     if (streq(argv[i],"-refresh")) {
  236.       refreshp = 1;
  237.       if (!text) text = GetStatusLine();
  238.     } 
  239.     else if (streq(argv[i],"-default")) {
  240.       prev = "-default";
  241.       text = WIN_DEFAULT_WINBAR;
  242.     }
  243.     else if (streq(argv[i],"-none")) {
  244.       prev = "-none";
  245.       refreshp = WinbarP = 0;
  246.     }
  247.     else if ((streq(argv[i],"-message")) && ((i+1)<argc)) {
  248.       text = argv[++i];
  249.       prev = "-message";
  250.     }
  251.     else if (*argv[i] != '-') {
  252.       prev = "-message";
  253.       text = argv[i];
  254.     }
  255.     else {
  256.       tcl_error("usage: %s [-i spawn_id] [-refresh] [-none | -default | -message string]", argv[0]);
  257.       return(TCL_ERROR);
  258.     }
  259.   }
  260.   if (refreshp) UpdateWindow(text);
  261.   else SetStatusLine(text);
  262.   sprintf(interp->result,"%s", prev);
  263.   if (prev[1] == 'm') /* message */
  264.     Tcl_AppendElement(interp, GetStatusLine(), 0);
  265.   return(TCL_OK);  
  266. }
  267.  
  268. /*ARGSUSED*/
  269. static int
  270. cmdTermSwitch(clientData, interp, argc, argv)
  271. ClientData clientData;
  272. Tcl_Interp *interp;
  273. int argc;
  274. char **argv;
  275. {
  276.   int m = -1, i;
  277.   int refreshp=0;
  278.   char temp_buf[32], *tmpstatus = NULL;
  279.   extern char *Strdup();
  280.  
  281.   /* get spawn id if any */
  282.   for (i=1;i<argc;i++) {
  283.       if (streq(argv[i],"-i")) {
  284.       if (argc == ++i) goto usage_error;
  285.       m = atoi(argv[i]);
  286.       break;
  287.       }
  288.   }
  289.  
  290.   /* get master fd */
  291.   if ((m == -1) && (update_master(&m) == 0)) return(TCL_ERROR);
  292.   if (m == -1) return(TCL_ERROR);
  293.   else if (m <= 2) {
  294.     tcl_error("%s: Invalid Master: %d",argv[0]);
  295.     return(TCL_ERROR);
  296.   }
  297.   if (!SetSessionFromFD(m)) {
  298.     tcl_error("spawn_id %d not associated with a terminal emulator.", m);
  299.     return(TCL_ERROR);
  300.   }
  301.  
  302.   /* parse rest of arguments */
  303.   for (i=1;i<argc;i++) {
  304.     if (streq(argv[i],"-i")) {
  305.       i++;
  306.     } else if (streq(argv[i],"-refresh")) {
  307.       refreshp = 1;
  308.     } else if (streq(argv[i],"-echo")) {
  309.     if (i+1 < argc) {
  310.       if (streq(argv[i+1],"-get")) {
  311.         i++;
  312.       } else if (streq(argv[i+1],"-on")) {
  313.         Session->echop = 1;
  314.         i++;
  315.       } else if (streq(argv[i+1],"-off")) {
  316.         Session->echop = 0;
  317.         i++;
  318.       } else if (streq(argv[i+1],"-toggle")) {
  319.         Session->echop = (Session->echop? 0 : 1);
  320.         i++;
  321.       }
  322.     }
  323.     sprintf(temp_buf,"%d",Session->echop);
  324.     Tcl_AppendElement(interp, temp_buf, 0);
  325.       } else if (streq(argv[i],"-tabspace")) {
  326.     if (i+1 < argc) {
  327.       if (streq(argv[i+1],"-get")) {
  328.         i++;
  329.       } else if (streq(argv[i+1],"-on")) {
  330.         Session->tabspacep = 1;
  331.         i++;
  332.       } else if (streq(argv[i+1],"-off")) {
  333.         Session->tabspacep = 0;
  334.         i++;
  335.       } else if (streq(argv[i+1],"-toggle")) {
  336.         Session->tabspacep = (Session->tabspacep? 0 : 1);
  337.         i++;
  338.       }
  339.     }
  340.     sprintf(temp_buf,"%d",Session->tabspacep);
  341.     Tcl_AppendElement(interp, temp_buf, 0);
  342.       } else if (streq(argv[i],"-all_breaks")) {
  343.     if (i+1 < argc) {
  344.       if (streq(argv[i+1],"-get")) {
  345.         i++;
  346.       } else if (streq(argv[i+1],"-on")) {
  347.         Session->breaksp = 1;
  348.         i++;
  349.       } else if (streq(argv[i+1],"-off")) {
  350.         Session->breaksp = 0;
  351.         i++;
  352.       } else if (streq(argv[i+1],"-toggle")) {
  353.         Session->breaksp = (Session->breaksp? 0 : 1);
  354.         i++;
  355.       }
  356.     }
  357.     sprintf(temp_buf,"%d",Session->tabspacep);
  358.     Tcl_AppendElement(interp, temp_buf, 0);
  359.       } else if (streq(argv[i],"-crnl")) {
  360.     if (i+1 < argc) {
  361.       if (streq(argv[i+1],"-get")) {
  362.         i++;
  363.       } else if (streq(argv[i+1],"-on")) {
  364.         Session->crnlp = 1;
  365.         i++;
  366.       } else if (streq(argv[i+1],"-off")) {
  367.         Session->crnlp = 0;
  368.         i++;
  369.       } else if (streq(argv[i+1],"-toggle")) {
  370.         Session->crnlp = (Session->crnlp? 0 : 1);
  371.         i++;
  372.       }
  373.     }
  374.     sprintf(temp_buf,"%d",Session->crnlp);
  375.     Tcl_AppendElement(interp, temp_buf, 0);
  376.     
  377.     /* log option */
  378.       } else if (streq(argv[i],"-log") || streq(argv[i],"-rawlog")) {
  379.     char *file=NULL, buf[128]; 
  380.     int raw = (argv[i][1] ==  'r'), logp = 2;
  381.     char *mode = "w";
  382.     FILE **Session_log;
  383.     char **Session_log_filename;
  384.  
  385.     for (++i;i<argc;i++) {
  386.       if ((streq(argv[i],"-file") && (++i<argc)) || (argv[i][0] != '-')) {
  387.         logp = 1;
  388.         if (NULL == (argv[i] = Tcl_TildeSubst(interp,argv[i])))
  389.           return TCL_ERROR;
  390.         file = argv[i];
  391.       } else if (streq(argv[i],"-get")) {
  392.         logp = 2;
  393.       } else if (streq(argv[i],"-raw")) {
  394.         raw = 1;
  395.       } else if (streq(argv[i],"-on")) {
  396.         logp = 1;
  397.       } else if (streq(argv[i],"-off")) {
  398.         logp = -1;
  399.       } else if (streq(argv[i],"-toggle")) {
  400.         logp = 0;
  401.       } else if (streq(argv[i],"-append")) {
  402.         mode = "a";
  403.       } else { --i; break; }
  404.     }
  405.     
  406.     if (raw) {
  407.       Session_log          = &(Session->raw_log);
  408.       Session_log_filename = &(Session->raw_log_filename);
  409.     } else {
  410.       Session_log          = &(Session->cooked_log);
  411.       Session_log_filename = &(Session->cooked_log_filename);
  412.     }
  413.  
  414.     if (logp == 2) { /* if just "getting" state info */
  415.       sprintf(temp_buf,"%s", (*Session_log ? *Session_log_filename : "0"));
  416.       Tcl_AppendElement(interp, temp_buf, 0);
  417.     }
  418.     else {
  419.       logp = (logp ? (logp + 1) : (!*Session_log));
  420.     
  421.       if (logp) {                      /* turn logging on */
  422.         if (file) {
  423.           if (*Session_log_filename) free(*Session_log_filename);
  424.           *Session_log_filename = (char *)Strdup(file);
  425.         }
  426.         if (!*Session_log_filename) {
  427.           file = buf;
  428.           sprintf(buf,"%s/ExpectLog.%s%d", ExpectLogDir, (raw ? "raw" : ""), m);
  429.           *Session_log_filename = (char *)Strdup(file);
  430.         }
  431.         *Session_log = fopen(*Session_log_filename,mode);
  432.         /* printf("Logfile: %s\n",*Session_log_filename); */
  433.         sprintf(buf,"%s Log: %s", (raw ? "Raw" : "Cooked"),
  434.             *Session_log_filename);
  435.         if (tmpstatus) free(tmpstatus);
  436.         tmpstatus = Strdup(buf);
  437.         sprintf(temp_buf,"%s", (*Session_log ? *Session_log_filename : "0"));
  438.         Tcl_AppendElement(interp, temp_buf, 0);
  439.       } else if (*Session_log) { /* turn logging off */
  440.         if (!raw) BFLUSH(0);
  441.         fclose(*Session_log); 
  442.         *Session_log = NULL;
  443.         sprintf(temp_buf,"%s", (*Session_log ? *Session_log_filename : "0"));
  444.         Tcl_AppendElement(interp, temp_buf, 0);
  445.       } else if (raw)
  446.         Tcl_AppendElement(interp, "0 Raw Logging already off", 0);
  447.       else 
  448.         Tcl_AppendElement(interp, "0 Logging already off", 0);
  449.     }
  450.       } else goto usage_error;
  451.   }
  452.   if (refreshp) {
  453.     UpdateWindow(tmpstatus);
  454.     if (tmpstatus) {
  455.       SetStatusLine(WIN_DEFAULT_WINBAR);
  456.       free(tmpstatus);
  457.     }
  458.   }
  459.   return(TCL_OK);
  460.  
  461.  usage_error:
  462.   tcl_error("usage: %s [-i spawn_id] [-refresh] [[-echo|-crnl|-tabspace|-all_breaks] [-on|-off|-toggle|-get]] \
  463. [[-log|-rawlog] [-append] [-on|-off|-toggle|-file string]", argv[0]);
  464.   return(TCL_ERROR);
  465. }
  466.  
  467. /*ARGSUSED*/
  468. static int
  469. cmdEmulate(clientData, interp, argc, argv)
  470. Tcl_Interp *interp;
  471. ClientData clientData;
  472. int argc;
  473. char **argv;
  474. {
  475.   int i = 1;
  476.   int m = -1;
  477.   int rows = 0;
  478.   int cols = 0;
  479.   char *emulate = NULL;
  480.   struct f *fp;
  481.  
  482.   for(i=1; i < argc; ++i) {
  483.     if (streq(argv[i],"-i")) {
  484.       if (++i == argc) goto usage_error;
  485.       else m = atoi(argv[i]);
  486.     }
  487.     else if (streq(argv[i],"-term")) {
  488.       if (++i == argc) goto usage_error;
  489.       else emulate = argv[i];
  490.     }
  491.     else if (streq(argv[i],"-rows")) {
  492.       if (++i == argc) goto usage_error;
  493.       else rows = atoi(argv[i]);
  494.     }
  495.     else if (streq(argv[i],"-cols")) {
  496.       if (++i == argc) goto usage_error;
  497.       else cols = atoi(argv[i]);
  498.     }
  499.     else if (streq(argv[i],"-get")) {
  500.     }
  501.     else if ('0' <= *argv[i] && (*argv[i] <= '9'))
  502.       m = atoi(argv[i]);
  503.     else emulate = argv[i];
  504.   }
  505.   if ((m == -1) && (update_master(&m) == 0)) return(TCL_ERROR);
  506.   if (m == -1) return(TCL_ERROR);
  507.   if (is_user(m)) {
  508.     tcl_error("cannot emulate with self - set spawn_id to a spawned process");
  509.     return(TCL_ERROR);
  510.   }
  511.   else if (m <= 2) {
  512.     tcl_error("%s: Invalid Master: %d",argv[0]);
  513.     return(TCL_ERROR);
  514.   }
  515.   if (emulate) {
  516.     if (!EmulateTerminal(emulate, m, rows, cols)) {
  517.       fp = fd_to_f(m);
  518.       tcl_error("FAILURE: %s -i %d %s", argv[0], m, emulate);
  519.       return(TCL_ERROR);
  520.     }
  521.   }
  522.   SetSessionFromFD(m);
  523.   sprintf(interp->result,"%s", ((Session && Session->term->type)?Session->term->type:"0"));
  524.   return(TCL_OK);
  525.   
  526.  usage_error:
  527.   tcl_error("usage: %s [-i spawn_id] [-get|[-term] term]", argv[0]);
  528.   return(TCL_ERROR);
  529. }
  530.  
  531. #define deleteProc (void (*)())0
  532. void
  533. init_switch_interpreter(interp)
  534. Tcl_Interp *interp;
  535. {
  536.   extern int cmdScreenInfo();
  537.   
  538.   Tcl_SetVar(interp,"term_type","vt100",0);
  539.   Tcl_SetVar(interp,"nonasci_char", "#",0);
  540.   Tcl_SetVar(interp,"screen_quiet", "0.0",0);
  541.   Tcl_SetVar(interp,"term_echo", ECHOP_DEFAULT,0);
  542.   Tcl_SetVar(interp,"term_crnl", CRNLP_DEFAULT,0);
  543.   Tcl_SetVar(interp,"term_tabspace", TABSPACEP_DEFAULT,0);
  544.   Tcl_SetVar(interp,"term_breaks", BREAKS_DEFAULT,0);
  545.  
  546.   Tcl_CreateCommand(interp,"screen_info",
  547.             cmdScreenInfo,(ClientData)0,deleteProc);
  548.   Tcl_CreateCommand(interp,"emulate",
  549.             cmdEmulate,(ClientData)0,deleteProc);
  550.   Tcl_CreateCommand(interp,"term_switch",
  551.             cmdTermSwitch,(ClientData)0,deleteProc);
  552.   Tcl_CreateCommand(interp,"set_master",
  553.             cmdSetMaster,(ClientData)0,deleteProc);
  554.   Tcl_CreateCommand(interp,"status_line",
  555.             cmdStatusLine,(ClientData)0,deleteProc);
  556.   Tcl_CreateCommand(interp,"term_info",
  557.             cmdTermInfo,(ClientData)0,deleteProc);
  558. }
  559.